use crate::io::{read_byte, write_byte};

const UART: usize = 0x10000000;
const UART_DAT: usize = UART + 0x00; // 数据寄存器

const UART_IER: usize = UART + 0x01; // 中断使能寄存器

const UART_IIR: usize = UART + 0x02; // 中断标识寄存器 (read only)

const UART_FCR: usize = UART + 0x02; // FIFO控制寄存器 (write only)

const UART_LCR: usize = UART + 0x03; // 线路控制寄存器

const UART_MCR: usize = UART + 0x04; // MODEN控制寄存器

const UART_LSR: usize = UART + 0x05; // 线路状态寄存器

const UART_MSR: usize = UART + 0x06; // MODEN状态寄存器

const UART_DLL: usize = UART + 0x00; // 预分频寄存器低8位

const UART_DLM: usize = UART + 0x01; // 预分频寄存器高8位

const UART_LSR_ERROR: usize = 0x80; // 出错

const UART_LSR_EMPTY: usize = 0x40; // 传输FIFO和移位寄存器为空

const UART_LSR_TFE: usize = 0x20; // 传输FIFO为空

const UART_LSR_BI: usize = 0x10; // 传输被打断

const UART_LSR_FE: usize = 0x08; // 接收到没有停止位的帧

const UART_LSR_PE: usize = 0x04; // 奇偶校验错误位

const UART_LSR_OE: usize = 0x02; // 数据溢出

const UART_LSR_DR: usize = 0x01; // FIFO有数据

const UART16550_CLOCK: u32 = 1843200; // a common base clock.
const UART_DEFAULT_BAUD: u32 = 115200;

#[unsafe(no_mangle)]
pub fn uart_init() {
    let divisor = UART16550_CLOCK / (16 * UART_DEFAULT_BAUD);

    // disable interrupt
    unsafe {
        write_byte(UART_IER, 0);

        // enable DLAB (set baud rate divisor)
        write_byte(UART_LCR, 0x80);
        write_byte(UART_DLL, divisor as u8);
        write_byte(UART_DLM, (divisor >> 8) as u8);

        // 8 bits, no parity, one stop bit.
        write_byte(UART_LCR, 0x3);

        // enable the fifo, clear fifo, set 14 bytes threshold.
        write_byte(UART_FCR, 0xc7);
    }
}

pub fn uart_send(byte: u8) {
    unsafe {
        while read_byte(UART_LSR) & UART_LSR_EMPTY as u8 == 0 {
            continue;
        }
        write_byte(UART_DAT, byte)
    }
}

pub fn uart_send_string(string: &str) {
    for s in string.as_bytes() {
        uart_send(*s);
    }
}
